// Copyright (c) 2021 百小僧, Baiqian Co.,Ltd.
// Util is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2. 
// You may obtain a copy of Mulan PSL v2 at:
//             https://gitee.com/dotnetchina/Util/blob/master/LICENSE
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
// See the Mulan PSL v2 for more details.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Terra.Core.Common.Utils;

/// <summary>
/// 参数检查
/// </summary>
public static class Check
{
    /// <summary>
    /// 验证参数不能为空引用，否则抛出<see cref="ArgumentNullException"/>异常。
    /// </summary>
    /// <param name="value">要验证的值</param>
    /// <param name="paramName">参数名称</param>
    public static void NotNull<T>(T value, string paramName)
    {
        if (value == null)
            throw new ArgumentNullException(paramName);
    }

    /// <summary>
    /// 验证字符串不能为空引用或空字符串，否则抛出<see cref="ArgumentNullException"/>异常或<see cref="ArgumentException"/>异常。
    /// </summary>
    /// <param name="value">要验证的字符串</param>
    /// <param name="paramName">参数名称</param>
    public static void NotNullOrEmpty(string value, string paramName)
    {
        if (value == null)
            throw new ArgumentNullException(paramName);
        if (value.Trim().Length == 0)
            throw new ArgumentException($"参数{paramName}不能为空字符串");
    }

    /// <summary>
    /// 验证集合不能为空引用或空集合，否则抛出<see cref="ArgumentNullException"/>异常或<see cref="ArgumentException"/>异常。
    /// </summary>
    /// <typeparam name="T">集合项的类型</typeparam>
    /// <param name="collection">要验证的集合</param>
    /// <param name="paramName">参数名称</param>
    public static void NotNullOrEmpty<T>(IEnumerable<T> collection, string paramName)
    {
        NotNull(collection, paramName);
        if (!collection.Any())
            throw new ArgumentException($"集合{paramName}不能为空");
    }

    /// <summary>
    /// 验证参数必须小于等于指定值，否则抛出<see cref="ArgumentOutOfRangeException"/>异常。
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="value">要验证的值</param>
    /// <param name="paramName">参数名称</param>
    /// <param name="compareValue">要比较的值</param>
    public static void LessThanOrEqual<T>(T value, string paramName, T compareValue) where T : IComparable<T>
    {
        if (value.CompareTo(compareValue) > 0)
            throw new ArgumentOutOfRangeException(paramName, $"参数{paramName}的值必须小于或等于{compareValue}");
    }

    /// <summary>
    /// 验证参数必须大于等于指定值，否则抛出<see cref="ArgumentOutOfRangeException"/>异常。
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="value">要验证的值</param>
    /// <param name="paramName">参数名称</param>
    /// <param name="compareValue">要比较的值</param>
    public static void GreaterThanOrEqual<T>(T value, string paramName, T compareValue) where T : IComparable<T>
    {
        if (value.CompareTo(compareValue) < 0)
            throw new ArgumentOutOfRangeException(paramName, $"参数{paramName}的值必须大于或等于{compareValue}");
    }

    /// <summary>
    /// 验证参数必须在指定范围内，否则抛出<see cref="ArgumentOutOfRangeException"/>异常。
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="value">要验证的值</param>
    /// <param name="paramName">参数名称</param>
    /// <param name="start">比较范围的起始值</param>
    /// <param name="end">比较范围的结束值</param>
    public static void Between<T>(T value, string paramName, T start, T end) where T : IComparable<T>
    {
        bool flag = value.CompareTo(start) >= 0 && value.CompareTo(end) <= 0;
        if (!flag)
            throw new ArgumentOutOfRangeException(paramName, $"参数{paramName}的值必须在{start}和{end}之间");
    }
}